#include "levelobjectstreewidget.h"
#include "modes/leveleditormode.h"
#include "levelObjects/level.h"
#include "levelObjects/levelobjectselectionmanager.h"
#include "document.h"
#include "application.h"
#include "utils.h"

LevelObjectsTreeWidget::LevelObjectsTreeWidget(QWidget *parent)
	: QTreeWidget(parent)
{
	connect(this, &QTreeWidget::itemSelectionChanged, 
		this, &LevelObjectsTreeWidget::onItemSelectionChanged);
}

void LevelObjectsTreeWidget::setLevelEditorMode( QPointer<Modes::EditorMode> lem )
{
	m_levelEditorMode = lem;
	connect(lem, &Modes::LevelEditorMode::documentChanged, 
		this, &LevelObjectsTreeWidget::onDocumentChanged);
}

void LevelObjectsTreeWidget::populateView()
{
	clear();

	QPointer<Modes::LevelEditorMode> lem = qobject_cast<Modes::LevelEditorMode*>(m_levelEditorMode);
	QPointer<LevelObjects::Level> level = qobject_cast<LevelObjects::Level*>(lem->selectedLevel());

	int index = 0;
	if(level)
	{
		const LevelObjects::Level::LevelActors& levelActors = level->levelActors();

		foreach(QPointer<LevelObjects::AbstractLevelObject> lo, levelActors)
		{
			LevelObjectsTreeWidgetItem* pNewItem = addLevelObject(lo);

			if(index++ == 0)
			{
				pNewItem->setSelected(true);
			}
		}
	}
}

void LevelObjectsTreeWidget::onLevelObjectAdded( QPointer<LevelObjects::AbstractLevelObject> lo )
{
	LevelObjectsTreeWidgetItem* pNewItem = addLevelObject(lo);

	// NOTE: blocking so we dont want to broadcast null selected object
	blockSignals(true);
	clearSelection();
	blockSignals(false);

	pNewItem->setSelected(true);
}

void LevelObjectsTreeWidget::onLevelObjectRemoved( QPointer<LevelObjects::AbstractLevelObject> lo )
{
	if(lo->type() == LevelObjects::LOT_Actor)
	{
		int index = 
			indexOfTopLevelItem(treeWidgetItemFromObject<LevelObjectsTreeWidgetItem, LevelObjects::AbstractLevelObject>(lo, this));
		QTreeWidgetItem* pItem = takeTopLevelItem(index);
		delete pItem;
	}
}

void LevelObjectsTreeWidget::onDocumentChanged( QPointer<Document> document )
{
	if(!document)
	{
		clear();
	}
}

void LevelObjectsTreeWidget::onItemSelectionChanged()
{
	QList<QTreeWidgetItem*> selItems = selectedItems();
	LevelObjects::LevelObjectSelectionManager::Selection selObjects;

	foreach(QTreeWidgetItem* pSelItem, selItems)
	{
		LevelObjectsTreeWidgetItem* pTWI = static_cast<LevelObjectsTreeWidgetItem*>(pSelItem);
		Q_ASSERT(pTWI);
		selObjects << pTWI->object;
	}

	m_currentLevel->selectionManager()->select(selObjects);
}

void LevelObjectsTreeWidget::onObjectDataChanged( QPointer<LevelObjects::AbstractLevelObject> lo )
{

}

void LevelObjectsTreeWidget::onSelectedLevelChanged( QPointer<LevelObjects::AbstractLevelObject> level )
{
	if(m_currentLevel)
	{
		disconnect(m_currentLevel, &LevelObjects::Level::levelObjectAdded, 
			this, &LevelObjectsTreeWidget::onLevelObjectAdded);
		disconnect(m_currentLevel, &LevelObjects::Level::levelObjectRemoved, 
			this, &LevelObjectsTreeWidget::onLevelObjectRemoved);
		disconnect(m_currentLevel->selectionManager(), 
			&LevelObjects::LevelObjectSelectionManager::objectSelectionChanged, 
			this, &LevelObjectsTreeWidget::onObjectSelectionChanged);
	}

	m_currentLevel = qobject_cast<LevelObjects::Level*>(level);

	if(m_currentLevel)
	{
		connect(m_currentLevel, &LevelObjects::Level::levelObjectAdded, 
			this, &LevelObjectsTreeWidget::onLevelObjectAdded);
		connect(m_currentLevel, &LevelObjects::Level::levelObjectRemoved, 
			this, &LevelObjectsTreeWidget::onLevelObjectRemoved);
		connect(m_currentLevel->selectionManager(), 
			&LevelObjects::LevelObjectSelectionManager::objectSelectionChanged, 
			this, &LevelObjectsTreeWidget::onObjectSelectionChanged);
	}

	populateView();
}

void LevelObjectsTreeWidget::onObjectSelectionChanged()
{
	// disconnect signals from selectionManager
	// pTreeWidgetItem->setSelected(true)
	// connect signals from selectedManager
}

LevelObjectsTreeWidgetItem* LevelObjectsTreeWidget::addLevelObject( QPointer<LevelObjects::AbstractLevelObject> lo )
{
	LevelObjectsTreeWidgetItem* pNewItem = new LevelObjectsTreeWidgetItem;
	pNewItem->object = lo;
	pNewItem->setText(0, lo->name());

	if(lo->type() == LevelObjects::LOT_Actor)
	{
		addTopLevelItem(pNewItem);
	}

	return pNewItem;
}
